"use strict";
/**
 * Copyright (c) 2015, Yaacov Zamir <kobi.zamir@gmail.com>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF  THIS SOFTWARE.
 */

/**
 * Take a MCProtocol serial function and convert it to use promises.
 *
 * @param {Function} f the function to convert
 * @return a function that calls function "f" and return a promise.
 * @private
 */
var _convert = function(f) {
    var converted = function(accessRoute, param, next) {
        var client = this;

        /* the function check for a callback
         * if we have a callback, use it
         * o/w build a promise.
         */
        if (next) {
            // if we have a callback, use the callback
            f.bind(client)(accessRoute, param, next);
        } else {
            // o/w use  a promise
            var promise = new Promise(function(resolve, reject) {
                function cb(err, data) {
                    if (err) {
                        reject(err);
                    } else {
                        resolve(data);
                    }
                }

                f.bind(client)(accessRoute, param, cb);
            });

            return promise;
        }
    };

    return converted;
};

/**
 * Adds promise API to a MCProtocol object.
 *
 * @param {MCProtocol} MCProtocol the MCProtocol object.
 */
var addPromiseAPI = function(MCProtocol) {

    var cl = MCProtocol.prototype;
    cl.readPLCDev = _convert(cl.writeDevRead);
    /* The just PLC device read command is implemented.
       other commands can be implemented. And promise APIs
       also will be provided here, like.....

    cl.readPLCLable = _convert(cl.writeLabelRead);
    cl.writePLCDev = _convert(cl.writeDevWrite);
            .
            .
            .
    */
};

/**
 * Promise API MCProtocol library.
 *
 * @type {addPromiseAPI}
 */
module.exports = addPromiseAPI;
